package com.bbcare.followup.plat.service.impl;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang.StringUtils;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONException;
import com.alibaba.fastjson.JSONObject;
import com.bbcare.comm.AppException;
import com.bbcare.comm.Constants;
import com.bbcare.comm.ErrorCode;
import com.bbcare.comm.SeqUtil;
import com.bbcare.comm.ToolUtils;
import com.bbcare.followup.plat.entity.ContentTemplVersion;
import com.bbcare.followup.plat.entity.FollowQueue;
import com.bbcare.followup.plat.entity.FollowScheme;
import com.bbcare.followup.plat.entity.FollowSchemeVersion;
import com.bbcare.followup.plat.entity.FollowTask;
import com.bbcare.followup.plat.entity.FollowTaskContent;
import com.bbcare.followup.plat.service.IPatientInfoHisService;
import com.bbcare.followup.plat.service.ISchemeService;
import com.bbcare.followup.plat.store.ibatis.IConfCacheDAO;
import com.bbcare.followup.plat.store.ibatis.IContentTemplDAO;
import com.bbcare.followup.plat.store.ibatis.IFollowQueueDAO;
import com.bbcare.followup.plat.store.ibatis.IFollowSchemeDAO;
import com.bbcare.followup.plat.store.ibatis.IFollowTaskContentDAO;
import com.bbcare.followup.plat.store.ibatis.IFollowTaskDAO;
import com.bbcare.followup.plat.store.ibatis.IPatientOperationRecordDAO;

/*
 * @name:         方案信息服务类实现
 * @author:       DemonLee
 * @createTime:   2017.4.26
 * @description:  方案相关操作等
 * @modify:
 *
 */
@Service
public class SchemeService implements ISchemeService {
    private final Log logger = LogFactory.getLog(SchemeService.class);

    @Autowired
    private IFollowSchemeDAO schemeDao;

    @Autowired
    private IPatientInfoHisService patientInfoHisService;

    @Autowired
    private IPatientOperationRecordDAO patientOperationRecordDao;

    @Autowired
    private IFollowTaskDAO followTaskDao;

    @Autowired
    private IFollowTaskContentDAO followTaskContDao;

    @Autowired
    private IFollowQueueDAO followQueueDao;

    @Autowired
    private IContentTemplDAO cntTemplDao;

    @Autowired
    private IConfCacheDAO confCacheDao;

    // 方案信息List查询接口实现
    public List<Map<String, Object>> getSchemeList(Map<String, Object> paramMap) throws Exception {
        logger.warn("--in getSchemeList--");

        Map<String, Object> argMap = new HashMap<String, Object>(paramMap);
        String schemeName = (String) argMap.get("schemeName");
        if (null != schemeName) {
            argMap.put("schemeName", schemeName + "%");// 模糊查询
        }
        argMap.put("schemeTypePrivate", Constants.SCHEME_TYPE_PRIVATE);
        argMap.put("schemeTypeTenant", Constants.SCHEME_TYPE_TENANT);
        argMap.put("schemeTypePublic", Constants.SCHEME_TYPE_PUBLIC);

        List<String> schemeStatusList = new ArrayList<String>();
        schemeStatusList.add(Constants.SCHEME_STATUS_DRAFT);
        schemeStatusList.add(Constants.SCHEME_STATUS_NORMAL);
        argMap.put("schemeStatusIn", schemeStatusList);

        List<Map<String, Object>> retOutList = new ArrayList<Map<String, Object>>();
        List<FollowScheme> fqList = schemeDao.selectSchemeByAuthority(argMap);
        if (null != fqList && 0 != fqList.size()) {
            int tol = fqList.size();
            int k = 0;
            FollowScheme fsVo = null;
            for (k = 0; k < tol; k++) {
                fsVo = fqList.get(k);
                Map<String, Object> fsMap = new HashMap<String, Object>();
                fsMap.put("createDate", fsVo.getCreateTime().substring(0, 10));
                fsMap.put("schemeId", fsVo.getId());
                fsMap.put("schemeName", fsVo.getSchemeName());
                fsMap.put("schemeAuthorId", fsVo.getAuthorId());
                fsMap.put("schemeAuthorName", fsVo.getAuthorName());
                fsMap.put("schemeVersion", fsVo.getNewVersion());

                String schemeState = "";
                if (Constants.SCHEME_INIT_VERSION == fsVo.getNewVersion()) {
                    schemeState = "新方案（待配置）";
                } else if (Constants.SCHEME_STATUS_DRAFT.equals(fsVo.getSchemeStatus())) {
                    schemeState = "未应用（新版本未生效）";
                } else if (Constants.SCHEME_STATUS_NORMAL.equals(fsVo.getSchemeStatus())) {
                    schemeState = "已应用";
                }
                fsMap.put("schemeState", schemeState);
                retOutList.add(fsMap);
            }
        }

        return retOutList;
    }

    // 方案新增接口实现
    @Transactional
    public String addSchemeInfo(Map<String, Object> paramMap) throws Exception {
        Map<String, Object> argMap = new HashMap<String, Object>(paramMap);

        String authorName = (String) argMap.get("authorName");
        String updateTime = (String) argMap.get("updateTime");
        String authorId = (String) argMap.get("authorId");
        String updateAccept = (String) argMap.get("updateAccept");
        String tenantId = (String) argMap.get("tenantId");
        String opCode = (String) argMap.get("opCode");
        String schemeName = (String) argMap.get("schemeName");

        // 校验方案名称是否已经存在
        Map<String, Object> qrySchemeMap = new HashMap<String, Object>();
        qrySchemeMap.put("authorId", authorId);
        qrySchemeMap.put("schemeName", schemeName);
        List<FollowScheme> fsList = schemeDao.selectSchemeByName(qrySchemeMap);
        if (null != fsList && 0 != fsList.size()) {
            throw (new AppException(ErrorCode.FOLLOWUP_EXCEPTION_TYPE_SCHEME_NAME_ALREADY_EXIST, "该方案名称已经存在，请更换名称!"));
        }

        // 入操作流水记录表 ia_operation_record
        Map<String, Object> paramRecord = new HashMap<String, Object>();
        paramRecord.put("userName", "");
        paramRecord.put("userId", "");
        paramRecord.put("queueId", "");
        paramRecord.put("authorId", authorId);
        paramRecord.put("opTime", updateTime);
        paramRecord.put("type", Constants.DOCTOR_ACTIVE_BUSI_TYPE_10);
        paramRecord.put("opUsertype", Constants.OPCODE_TYPE_DOCTOR);
        paramRecord.put("authorName", authorName);
        paramRecord.put("opCode", opCode);
        paramRecord.put("updateAccept", updateAccept);
        paramRecord.put("tenantId", tenantId);
        paramRecord.put("remark", argMap.get("opNote"));
        paramRecord.put("opType", argMap.get("opType"));
        Map<String, Object> outRecord = patientInfoHisService.buildOperationRecord(paramRecord);
        patientOperationRecordDao.saveOperationRecord(outRecord);

        int totalTaskNum = (Integer) argMap.get("schemeTaskNum");// 总任务数
        int cycleDay = (Integer) argMap.get("schemeCycle");// 周期
        int warnDay = (Integer) argMap.get("schemeWarnDay");// 警戒期
        int windowDay = (Integer) argMap.get("schemeWindowDay");// 窗口期
        String schemeId = SeqUtil.getSeqNo(Constants.SEQ_NO_FOR_SCHEMEID);// 方案id

        // 入方案信息表 fu_scheme_info
        FollowScheme fsVo = new FollowScheme();
        fsVo.setAuthorId(authorId);
        fsVo.setAuthorName(authorName);
        fsVo.setCreateTime(updateTime);
        fsVo.setCycleDay(cycleDay);
        fsVo.setExecuteType(Constants.SCHEME_TASK_EXECUTE_TYPE_1);// 默认值: 纠正年龄触发
        fsVo.setId(schemeId);
        fsVo.setNewVersion(Constants.SCHEME_INIT_VERSION);
        fsVo.setSchemeIntro((String) argMap.get("schemeIntroduce"));
        fsVo.setSchemeName(schemeName);
        fsVo.setSchemeStatus(Constants.SCHEME_STATUS_NORMAL);
        fsVo.setSchemeType((String) argMap.get("schemeType"));
        fsVo.setTenantId(tenantId);
        fsVo.setTotalTime(totalTaskNum);
        fsVo.setUpdateAccept(updateAccept);
        fsVo.setUpdateTime(updateTime);
        fsVo.setWarnDay(warnDay);
        fsVo.setWindowDay(windowDay);
        schemeDao.saveSchemeInfo(fsVo);

        // 入方案版本变更记录表 fu_schemeversion_info
        String schemeVerId = SeqUtil.getSeqNo(Constants.SEQ_NO_FOR_SCHEMEVERSIONID);// 当前方案版本id
        FollowSchemeVersion fsvVo = new FollowSchemeVersion();
        fsvVo.setAuthorId(authorId);
        fsvVo.setCreateTime(updateTime);
        fsvVo.setId(schemeVerId);
        fsvVo.setRemark("新方案，初始版本");
        fsvVo.setSchemeData("");
        fsvVo.setSchemeId(schemeId);
        fsvVo.setSchemeVersion(Constants.SCHEME_INIT_VERSION);
        fsvVo.setUpdateAccept(updateAccept);
        fsvVo.setUpdateTime(updateTime);
        schemeDao.saveSchemeVersionInfo(fsvVo);

        // 入方案任务信息表 fu_task_info
        List<FollowTask> ftList = new ArrayList<FollowTask>();
        int it = 0;
        String nextTaskId = "";
        String currTaskId = SeqUtil.getSeqNo(Constants.SEQ_NO_FOR_TASKID);
        for (it = 0; it < totalTaskNum; it++) {
            if (it == totalTaskNum - 1) {
                nextTaskId = "";// 最后一次任务不需要
            } else {
                nextTaskId = SeqUtil.getSeqNo(Constants.SEQ_NO_FOR_TASKID);
            }
            FollowTask ftVo = new FollowTask();
            ftVo.setAuthorId(authorId);
            ftVo.setCreateTime(updateTime);
            ftVo.setExecuteAddress("");// 门诊地址，暂无
            ftVo.setExecuteDay(it * cycleDay);
            ftVo.setExecuteType(Constants.SCHEME_TASK_EXECUTE_TYPE_1);// 默认值:纠正年龄触发
            ftVo.setId(currTaskId);// task_id
            ftVo.setInformFlag("3");// 通知方式，暂无，先写死3
            ftVo.setSchemeVersionid(schemeVerId);
            ftVo.setSeqNo(it);
            ftVo.setNextTaskId(nextTaskId);
            if (0 == it) {
                ftVo.setTaskName("建档");
                ftVo.setTaskIntro("建档信息");
                ftVo.setCycleDay(0);
                ftVo.setWarnDay(0);
                ftVo.setWindowDay(0);
                ftVo.setSuffixWindowDay(0);
            } else {
                ftVo.setTaskName("第" + it + "次随访");
                ftVo.setTaskIntro("第" + it + "次随访");
                ftVo.setCycleDay(cycleDay);
                ftVo.setWarnDay(warnDay);
                ftVo.setWindowDay(windowDay / 2);// 任务前窗口期
                ftVo.setSuffixWindowDay(windowDay / 2);// 任务后窗口期
            }
            ftVo.setUpdateAccept(updateAccept);
            ftVo.setUpdateTime(updateTime);
            ftVo.setSchemeId(schemeId);
            ftVo.setTaskType(Constants.TASK_TYPE_SCHEME_SCHEDULE);// 默认门诊任务
            currTaskId = nextTaskId;

            ftList.add(ftVo);
        }
        followTaskDao.saveTaskBatch(ftList);// 一次性批量插入

        return schemeId;
    }

    // 方案删除接口实现
    @Transactional
    public void delSchemeInfo(Map<String, Object> paramMap) throws Exception {
        logger.warn("--in delSchemeInfo--");
        Map<String, Object> argMap = new HashMap<String, Object>(paramMap);

        String authorName = (String) argMap.get("authorName");
        String updateTime = (String) argMap.get("updateTime");
        String authorId = (String) argMap.get("authorId");
        String updateAccept = (String) argMap.get("updateAccept");
        String tenantId = (String) argMap.get("tenantId");
        String opCode = (String) argMap.get("opCode");
        String schemeId = (String) argMap.get("schemeId");

        // 校验方案是否存在
        Map<String, Object> qrySchemeMap = new HashMap<String, Object>();
        qrySchemeMap.put("id", schemeId);
        List<FollowScheme> fsList = schemeDao.selectById(qrySchemeMap);
        if (null == fsList || 0 == fsList.size()) {
            throw (new AppException(ErrorCode.FOLLOWUP_EXCEPTION_TYPE_SCHEME_NOT_EXIST, "方案不存在，删除失败!"));
        }

        // 校验方案失访已经被相关队列使用
        qrySchemeMap.clear();
        qrySchemeMap.put("schemeId", schemeId);
        List<FollowQueue> fqList = followQueueDao.selectBySchemeId(qrySchemeMap);
        if (null != fqList && 0 != fqList.size()) {
            throw (new AppException(ErrorCode.FOLLOWUP_EXCEPTION_TYPE_SCHEME_ALREADY_USED, "方案已被应用到队列中，无法删除!"));
        }

        // 入操作流水记录表 ia_operation_record
        Map<String, Object> paramRecord = new HashMap<String, Object>();
        paramRecord.put("userName", "");
        paramRecord.put("userId", "");
        paramRecord.put("queueId", "");
        paramRecord.put("authorId", authorId);
        paramRecord.put("opTime", updateTime);
        paramRecord.put("type", Constants.DOCTOR_ACTIVE_BUSI_TYPE_10);
        paramRecord.put("opUsertype", Constants.OPCODE_TYPE_DOCTOR);
        paramRecord.put("authorName", authorName);
        paramRecord.put("opCode", opCode);
        paramRecord.put("updateAccept", updateAccept);
        paramRecord.put("tenantId", tenantId);
        paramRecord.put("remark", argMap.get("opNote"));
        paramRecord.put("opType", argMap.get("opType"));
        Map<String, Object> outRecord = patientInfoHisService.buildOperationRecord(paramRecord);
        patientOperationRecordDao.saveOperationRecord(outRecord);

        // 更新方案状态为已删除
        qrySchemeMap.clear();
        qrySchemeMap.put("id", schemeId);
        qrySchemeMap.put("schemeStatus", Constants.SCHEME_STATUS_DELETE);
        qrySchemeMap.put("updateAccept", updateAccept);
        qrySchemeMap.put("updateTime", updateTime);
        schemeDao.modSchemeInfo(qrySchemeMap);

        return;
    }

    // 方案更新接口实现
    @Transactional
    public void modSchemeInfo(Map<String, Object> paramMap) throws Exception {
        logger.warn("--in modSchemeInfo--");
        Map<String, Object> argMap = new HashMap<String, Object>(paramMap);

        String authorName = (String) argMap.get("authorName");
        String updateTime = (String) argMap.get("updateTime");
        String authorId = (String) argMap.get("authorId");
        String updateAccept = (String) argMap.get("updateAccept");
        String tenantId = (String) argMap.get("tenantId");
        String opCode = (String) argMap.get("opCode");
        String schemeId = (String) argMap.get("schemeId");
        String schemeName = (String) argMap.get("schemeName");

        // 校验方案是否存在
        Map<String, Object> qrySchemeMap = new HashMap<String, Object>();
        qrySchemeMap.put("id", schemeId);
        List<FollowScheme> fsList = schemeDao.selectById(qrySchemeMap);
        if (null == fsList || 0 == fsList.size()) {
            throw (new AppException(ErrorCode.FOLLOWUP_EXCEPTION_TYPE_SCHEME_NOT_EXIST, "方案不存在，更新失败!"));
        }

        // 校验新方案名称是否已被使用
        qrySchemeMap.clear();
        qrySchemeMap.put("authorId", authorId);
        qrySchemeMap.put("schemeName", schemeName);
        qrySchemeMap.put("id", schemeId);
        qrySchemeMap.put("idReverseFlag", "1");
        List<FollowScheme> fnewList = schemeDao.selectSchemeByName(qrySchemeMap);
        if (null != fnewList && 0 != fnewList.size()) {
            throw (new AppException(ErrorCode.FOLLOWUP_EXCEPTION_TYPE_SCHEME_NAME_ALREADY_EXIST, "该方案名称已经存在，请更换名称!"));
        }

        // 入操作流水记录表 ia_operation_record
        Map<String, Object> paramRecord = new HashMap<String, Object>();
        paramRecord.put("userName", "");
        paramRecord.put("userId", "");
        paramRecord.put("queueId", "");
        paramRecord.put("authorId", authorId);
        paramRecord.put("opTime", updateTime);
        paramRecord.put("type", Constants.DOCTOR_ACTIVE_BUSI_TYPE_10);
        paramRecord.put("opUsertype", Constants.OPCODE_TYPE_DOCTOR);
        paramRecord.put("authorName", authorName);
        paramRecord.put("opCode", opCode);
        paramRecord.put("updateAccept", updateAccept);
        paramRecord.put("tenantId", tenantId);
        paramRecord.put("remark", argMap.get("opNote"));
        paramRecord.put("opType", argMap.get("opType"));
        Map<String, Object> outRecord = patientInfoHisService.buildOperationRecord(paramRecord);
        patientOperationRecordDao.saveOperationRecord(outRecord);

        // 更新方案名称
        qrySchemeMap.clear();
        qrySchemeMap.put("id", schemeId);
        qrySchemeMap.put("schemeName", schemeName);
        qrySchemeMap.put("updateAccept", updateAccept);
        qrySchemeMap.put("updateTime", updateTime);
        schemeDao.modSchemeInfo(qrySchemeMap);

        return;
    }

    // 方案任务列表接口实现
    public List<Object> qrySchemeTaskList(Map<String, Object> paramMap) throws Exception {
        HashMap<String, Object> argMap = new HashMap<String, Object>(paramMap);

        Map<String, Object> qrySchemeMap = new HashMap<String, Object>();
        qrySchemeMap.put("schemeId", argMap.get("fuSchemeId"));
        qrySchemeMap.put("schemeVersion", argMap.get("schemeVersion"));
        List<FollowSchemeVersion> fsvList = schemeDao.selectBySchemeIdAndVersion(qrySchemeMap);
        if (null == fsvList || 0 == fsvList.size()) {
            throw (new AppException(ErrorCode.FOLLOWUP_EXCEPTION_TYPE_SCHEMEVERSION_NOT_EXIST, "方案版本记录不存在!"));
        }
        FollowSchemeVersion fsvVo = fsvList.get(0);

        Map<String, Object> qryTaskMap = new HashMap<String, Object>();
        qryTaskMap.put("schemeVersionid", fsvVo.getId());
        List<FollowTask> ptList = followTaskDao.selectBySchemeVersionid(qryTaskMap);
        if (null == ptList || 0 == ptList.size()) {
            throw (new AppException(ErrorCode.FOLLOWUP_EXCEPTION_TYPE_SCHEME_TASK_NOT_EXIST, "该方案下无任务记录!"));
        }

        List<Object> retList = new ArrayList<Object>();
        int ipt = 0;
        for (; ipt < ptList.size(); ipt++) {
            HashMap<String, Object> ptMap = new HashMap<String, Object>();
            FollowTask futask = ptList.get(ipt);
            ptMap.put("taskId", futask.getId());
            ptMap.put("schemeVersionid", futask.getSchemeVersionid());
            ptMap.put("taskName", futask.getTaskName());
            ptMap.put("taskIntro", futask.getTaskIntro());
            ptMap.put("executeType", futask.getExecuteType());
            ptMap.put("seqNo", futask.getSeqNo());
            ptMap.put("taskCycleDay", futask.getCycleDay());
            ptMap.put("taskWindowDay", futask.getWindowDay());
            ptMap.put("taskWarnDay", futask.getWarnDay());
            ptMap.put("taskExecuteDay", futask.getExecuteDay());
            ptMap.put("informFlag", futask.getInformFlag());

            retList.add(ptMap);
        }

        return retList;
    }

    // 方案下某项任务信息更新接口实现
    @Transactional
    public void modSchemeTaskInfo(Map<String, Object> paramMap) throws Exception {
        Map<String, Object> argMap = new HashMap<String, Object>(paramMap);

        Map<String, Object> oprInfoMap = ToolUtils.typeCast(argMap.get("oprInfo"));
        Map<String, Object> taskInfoMap = ToolUtils.typeCast(argMap.get("taskInfo"));

        String authorName = (String) oprInfoMap.get("authorName");
        String updateTime = (String) oprInfoMap.get("updateTime");
        String authorId = (String) oprInfoMap.get("authorId");
        String updateAccept = (String) oprInfoMap.get("updateAccept");
        String tenantId = (String) oprInfoMap.get("tenantId");
        String opCode = (String) oprInfoMap.get("opCode");

        // 调用统一方法，将现有版本备份，新增版本
        Map<String, Object> outDealMap = this.dealSchemeVersionInfo(paramMap);
        String schemeVersionid = (String) outDealMap.get("schemeVersionid");// 草稿方案版本id

        // 更新任务信息
        taskInfoMap.put("schemeVersionid", schemeVersionid);
        taskInfoMap.put("updateTime", updateTime);
        taskInfoMap.put("updateAccept", updateAccept);
        followTaskDao.updateTaskInfoByTaskIdAndSchemeVerId(taskInfoMap);

        // 入操作流水记录表 ia_operation_record
        Map<String, Object> paramRecord = new HashMap<String, Object>();
        paramRecord.put("userName", "");
        paramRecord.put("userId", "");
        paramRecord.put("queueId", "");
        paramRecord.put("authorId", authorId);
        paramRecord.put("opTime", updateTime);
        paramRecord.put("type", Constants.DOCTOR_ACTIVE_BUSI_TYPE_10);
        paramRecord.put("opUsertype", Constants.OPCODE_TYPE_DOCTOR);
        paramRecord.put("authorName", authorName);
        paramRecord.put("opCode", opCode);
        paramRecord.put("updateAccept", updateAccept);
        paramRecord.put("tenantId", tenantId);
        paramRecord.put("remark", oprInfoMap.get("opNote"));
        paramRecord.put("opType", oprInfoMap.get("opType"));
        Map<String, Object> outRecord = patientInfoHisService.buildOperationRecord(paramRecord);
        patientOperationRecordDao.saveOperationRecord(outRecord);

        return;
    }

    // 方案版本变更通用接口实现
    public Map<String, Object> dealSchemeVersionInfo(Map<String, Object> paramMap) throws Exception {
        Map<String, Object> argMap = new HashMap<String, Object>(paramMap);
        Map<String, Object> outRetMap = new HashMap<String, Object>();

        Map<String, Object> oprInfoMap = ToolUtils.typeCast(argMap.get("oprInfo"));
        Map<String, Object> taskInfoMap = ToolUtils.typeCast(argMap.get("taskInfo"));
        String updateTime = (String) oprInfoMap.get("updateTime");
        String authorId = (String) oprInfoMap.get("authorId");
        String updateAccept = (String) oprInfoMap.get("updateAccept");
        String schemeId = (String) taskInfoMap.get("schemeId");

        // 0.防止多人同时修改方案造成并发问题，这里先锁表
        Map<String, Object> modMap = new HashMap<String, Object>();
        modMap.put("id", schemeId);
        modMap.put("updateAccept", updateAccept);
        modMap.put("updateTime", updateTime);
        schemeDao.modSchemeInfo(modMap);

        // 1.校验方案是否存在
        Map<String, Object> qrySchemeMap = new HashMap<String, Object>();
        qrySchemeMap.put("id", schemeId);
        List<FollowScheme> fsList = schemeDao.selectById(qrySchemeMap);
        if (null == fsList || 0 == fsList.size()) {
            throw (new AppException(ErrorCode.FOLLOWUP_EXCEPTION_TYPE_SCHEME_NOT_EXIST, "方案不存在，更新失败!"));
        }
        FollowScheme fshVo = fsList.get(0);

        Map<String, Object> qrySchemeVerMap = new HashMap<String, Object>();
        qrySchemeVerMap.put("schemeId", schemeId);

        // 2.判断当前方案的状态（0表示未发布正在修改，1表示已发布，此时需要修改为0状态）
        String schemeStatus = fshVo.getSchemeStatus();
        outRetMap.put("schemeStatus", schemeStatus);
        outRetMap.put("schemeVersion", fshVo.getNewVersion() + 1);

        if (Constants.SCHEME_STATUS_DELETE.equals(schemeStatus)) {
            throw (new AppException(ErrorCode.FOLLOWUP_EXCEPTION_TYPE_SCHEME_ALREADY_DELETE, "方案状态为已删除，无法处理!"));
        } else if (Constants.SCHEME_STATUS_DRAFT.equals(schemeStatus)) {
            qrySchemeVerMap.put("schemeVersion", fshVo.getNewVersion() + 1);// 草稿状态，版本加1，查询最新版本
            List<FollowSchemeVersion> fsvList = schemeDao.selectBySchemeIdAndVersion(qrySchemeVerMap);
            if (null == fsvList || 0 == fsvList.size()) {
                throw (new AppException(ErrorCode.FOLLOWUP_EXCEPTION_TYPE_SCHEMEVERSION_NOT_EXIST, "方案版本记录不存在!"));
            }
            FollowSchemeVersion fsvVo = fsvList.get(0);
            outRetMap.put("schemeVersionid", fsvVo.getId());

            return outRetMap;
        } else if (!Constants.SCHEME_STATUS_NORMAL.equals(schemeStatus)) {
            throw (new AppException(ErrorCode.FOLLOWUP_EXCEPTION_TYPE_SCHEME_STATUS_UNKNOWN, "方案状态未定义，无法处理!"));
        }
        qrySchemeVerMap.put("schemeVersion", fshVo.getNewVersion());// 发布状态，查询当前版本
        List<FollowSchemeVersion> fsvList = schemeDao.selectBySchemeIdAndVersion(qrySchemeVerMap);
        if (null == fsvList || 0 == fsvList.size()) {
            throw (new AppException(ErrorCode.FOLLOWUP_EXCEPTION_TYPE_SCHEMEVERSION_NOT_EXIST, "方案版本记录不存在!"));
        }
        FollowSchemeVersion fsvVo = fsvList.get(0);
        String currSchemeVersionId = fsvVo.getId();

        // 3.当前方案状态为1已发布，则需要更新为0草稿状态
        modMap.put("schemeStatus", Constants.SCHEME_STATUS_DRAFT);
        schemeDao.modSchemeInfo(modMap);

        // 4.fu_schemeversion_info新增一个版本
        String schemeVerId = SeqUtil.getSeqNo(Constants.SEQ_NO_FOR_SCHEMEVERSIONID);// 新方案版本id
        outRetMap.put("schemeVersionid", schemeVerId);
        FollowSchemeVersion fwshvVo = new FollowSchemeVersion();
        fwshvVo.setAuthorId(authorId);
        fwshvVo.setCreateTime(updateTime);
        fwshvVo.setId(schemeVerId);
        fwshvVo.setRemark((String) oprInfoMap.get("opNote"));
        fwshvVo.setSchemeId(schemeId);
        fwshvVo.setSchemeVersion(fshVo.getNewVersion() + 1);
        fwshvVo.setUpdateAccept(updateAccept);
        fwshvVo.setUpdateTime(updateTime);
        schemeDao.saveSchemeVersionInfo(fwshvVo);

        // 5.fu_task_info新增一个版本记录
        Map<String, Object> taskUpMap = new HashMap<String, Object>();
        taskUpMap.put("authorId", authorId);
        taskUpMap.put("updateTime", updateTime);
        taskUpMap.put("createTime", updateTime);
        taskUpMap.put("updateAccept", updateAccept);
        taskUpMap.put("newSchemeVersionid", schemeVerId);
        taskUpMap.put("oldSchemeVersionid", currSchemeVersionId);
        int iret = followTaskDao.saveNewTaskInfoBySchemeVerId(taskUpMap);
        if (0 == iret) {
            throw (new AppException(ErrorCode.FOLLOWUP_EXCEPTION_TYPE_SCHEME_TASK_NOT_EXIST, "方案下任务记录不存在!"));
        }

        // 6.fu_taskcontent_info新增一个版本记录
        Map<String, Object> taskConMap = new HashMap<String, Object>();
        taskConMap.put("updateTime", updateTime);
        taskConMap.put("createTime", updateTime);
        taskConMap.put("updateAccept", updateAccept);
        taskConMap.put("newSchemeVersionid", schemeVerId);
        taskConMap.put("oldSchemeVersionid", currSchemeVersionId);
        followTaskContDao.saveTaskContNewVersion(taskUpMap);

        return outRetMap;
    }

    // 方案下某项任务信息删除接口实现
    @Transactional
    public void delSchemeTaskInfo(Map<String, Object> paramMap) throws Exception {
        Map<String, Object> argMap = new HashMap<String, Object>(paramMap);

        Map<String, Object> oprInfoMap = ToolUtils.typeCast(argMap.get("oprInfo"));
        Map<String, Object> taskInfoMap = ToolUtils.typeCast(argMap.get("taskInfo"));

        String authorName = (String) oprInfoMap.get("authorName");
        String updateTime = (String) oprInfoMap.get("updateTime");
        String authorId = (String) oprInfoMap.get("authorId");
        String updateAccept = (String) oprInfoMap.get("updateAccept");
        String tenantId = (String) oprInfoMap.get("tenantId");
        String opCode = (String) oprInfoMap.get("opCode");

        // 调用统一方法，将现有版本备份，新增版本
        Map<String, Object> outDealMap = this.dealSchemeVersionInfo(paramMap);
        String schemeVersionid = (String) outDealMap.get("schemeVersionid");// 草稿方案版本id

        // 删除任务信息
        taskInfoMap.put("schemeVersionid", schemeVersionid);
        followTaskDao.deleteTaskInfoByTaskIdAndSchemeVerId(taskInfoMap);

        // 入操作流水记录表 ia_operation_record
        Map<String, Object> paramRecord = new HashMap<String, Object>();
        paramRecord.put("userName", "");
        paramRecord.put("userId", "");
        paramRecord.put("queueId", "");
        paramRecord.put("authorId", authorId);
        paramRecord.put("opTime", updateTime);
        paramRecord.put("type", Constants.DOCTOR_ACTIVE_BUSI_TYPE_10);
        paramRecord.put("opUsertype", Constants.OPCODE_TYPE_DOCTOR);
        paramRecord.put("authorName", authorName);
        paramRecord.put("opCode", opCode);
        paramRecord.put("updateAccept", updateAccept);
        paramRecord.put("tenantId", tenantId);
        paramRecord.put("remark", oprInfoMap.get("opNote"));
        paramRecord.put("opType", oprInfoMap.get("opType"));
        Map<String, Object> outRecord = patientInfoHisService.buildOperationRecord(paramRecord);
        patientOperationRecordDao.saveOperationRecord(outRecord);

        return;
    }

    // 提交方案下所有任务修改的内容接口实现
    @Transactional
    public void submitSchemeInfo(Map<String, Object> paramMap) throws Exception {
        Map<String, Object> argMap = new HashMap<String, Object>(paramMap);

        Map<String, Object> oprInfoMap = ToolUtils.typeCast(argMap.get("oprInfo"));
        Map<String, Object> schemeInfoMap = ToolUtils.typeCast(argMap.get("schemeInfo"));

        String authorName = (String) oprInfoMap.get("authorName");
        String updateTime = (String) oprInfoMap.get("updateTime");
        String authorId = (String) oprInfoMap.get("authorId");
        String updateAccept = (String) oprInfoMap.get("updateAccept");
        String tenantId = (String) oprInfoMap.get("tenantId");
        String opCode = (String) oprInfoMap.get("opCode");
        String schemeId = (String) schemeInfoMap.get("schemeId");

        // 防止多人同时修改方案造成并发问题，这里先锁表
        Map<String, Object> modMap = new HashMap<String, Object>();
        modMap.put("id", schemeId);
        modMap.put("updateAccept", updateAccept);
        modMap.put("updateTime", updateTime);
        int iret = schemeDao.modSchemeInfo(modMap);
        if (0 == iret) {
            throw (new AppException(ErrorCode.FOLLOWUP_EXCEPTION_TYPE_SCHEME_NOT_EXIST, "方案不存在，提交失败!"));
        }

        // 判断当前方案的状态（0表示未发布正在修改）
        Map<String, Object> qrySchemeMap = new HashMap<String, Object>();
        qrySchemeMap.put("id", schemeId);
        List<FollowScheme> fsList = schemeDao.selectById(qrySchemeMap);
        FollowScheme fshVo = fsList.get(0);
        String schemeStatus = fshVo.getSchemeStatus();
        if (!Constants.SCHEME_STATUS_DRAFT.equals(schemeStatus)) {
            throw (new AppException(ErrorCode.FOLLOWUP_EXCEPTION_TYPE_SCHEME_STATUS_IRREGULAR,
                    "方案状态不正常（不是未应用状态），无法提交!"));
        }

        // 更新方案版本+1，且将方案状态更新为1（已发布）
        modMap.put("schemeStatus", Constants.SCHEME_STATUS_NORMAL);
        modMap.put("schemeVersionAdd", "1");
        schemeDao.modSchemeInfo(modMap);

        // 入操作流水记录表 ia_operation_record
        Map<String, Object> paramRecord = new HashMap<String, Object>();
        paramRecord.put("userName", "");
        paramRecord.put("userId", "");
        paramRecord.put("queueId", "");
        paramRecord.put("authorId", authorId);
        paramRecord.put("opTime", updateTime);
        paramRecord.put("type", Constants.DOCTOR_ACTIVE_BUSI_TYPE_10);
        paramRecord.put("opUsertype", Constants.OPCODE_TYPE_DOCTOR);
        paramRecord.put("authorName", authorName);
        paramRecord.put("opCode", opCode);
        paramRecord.put("updateAccept", updateAccept);
        paramRecord.put("tenantId", tenantId);
        paramRecord.put("remark", oprInfoMap.get("opNote"));
        paramRecord.put("opType", oprInfoMap.get("opType"));
        Map<String, Object> outRecord = patientInfoHisService.buildOperationRecord(paramRecord);
        patientOperationRecordDao.saveOperationRecord(outRecord);

        return;
    }

    // 随访任务内容模板列表查询接口实现
    public Map<String, Object> listTaskContentTempl(Map<String, Object> paramMap) throws Exception {
        Map<String, Object> outMap = new HashMap<String, Object>();
        List<Object> outList = new ArrayList<Object>();
        outMap.put("total", 0);
        outMap.put("rows", outList);

        Map<String, Object> argMap = new HashMap<String, Object>(paramMap);
        String authorId = (String) argMap.get("authorId");
        String tenantId = (String) argMap.get("tenantId");

        // 查询内容分类
        Map<String, Object> classIn = new HashMap<String, Object>();
        classIn.put("classId", argMap.get("classId"));
        List<Map<String, Object>> classList = confCacheDao.listContentClass(classIn);
        if (CollectionUtils.isEmpty(classList)) {
            return outMap;
        }

        int clsize = classList.size();
        int c = 0;
        for (c = 0; c < clsize; c++) {
            Map<String, Object> classMap = classList.get(c);
            // 查询内容分组
            Map<String, Object> cntMapIn = new HashMap<String, Object>();
            cntMapIn.put("classId", classMap.get("id"));
            cntMapIn.put("QuesTypePrivate", Constants.QUESTION_TYPE_PRIVATE);
            cntMapIn.put("QuesTypeTenant", Constants.QUESTION_TYPE_TENANT);
            cntMapIn.put("QuesTypePublic", Constants.QUESTION_TYPE_PUBLIC);
            cntMapIn.put("status", Constants.TABLE_RECORD_STATUS_NOMAL);
            cntMapIn.put("authorId", authorId);
            cntMapIn.put("tenantId", tenantId);
            List<Map<String, Object>> groupList = cntTemplDao.listTemplGroupIdByAuthority(cntMapIn);
            if (!CollectionUtils.isEmpty(groupList)) {
                int gg = 0;
                int gsize = groupList.size();
                for (gg = 0; gg < gsize; gg++) {
                    Map<String, Object> groupMap = groupList.get(gg);
                    // 查询内容模板
                    cntMapIn.put("contentGroupid", groupMap.get("contentGroupid"));
                    List<Map<String, Object>> cntTemplList = cntTemplDao.listTemplByAuthorityAndClassId(cntMapIn);
                    groupMap.put("Cntlist", cntTemplList);
                }
                classMap.put("groupList", groupList);
            }
        }
        outMap.put("total", classList.size());
        outMap.put("rows", classList);

        return outMap;
    }

    // 给当前方案当前任务新增某项任务内容接口实现
    @Override
    @Transactional
    public Map<String, Object> saveSchemeTaskCont(Map<String, Object> paramMap) throws Exception {
        Map<String, Object> argMap = new HashMap<String, Object>(paramMap);
        Map<String, Object> outMap = new HashMap<String, Object>();

        Map<String, Object> oprInfoMap = ToolUtils.typeCast(argMap.get("oprInfo"));
        Map<String, Object> taskInfoMap = ToolUtils.typeCast(argMap.get("taskInfo"));

        String authorName = (String) oprInfoMap.get("authorName");
        String updateTime = (String) oprInfoMap.get("updateTime");
        String authorId = (String) oprInfoMap.get("authorId");
        String updateAccept = (String) oprInfoMap.get("updateAccept");
        String tenantId = (String) oprInfoMap.get("tenantId");
        String opCode = (String) oprInfoMap.get("opCode");

        String taskId = (String) taskInfoMap.get("taskId");
        String templId = (String) taskInfoMap.get("templId");
        int templVersion = (Integer) taskInfoMap.get("templVersion");

        // 调用统一方法，将现有版本备份，新增版本
        Map<String, Object> outDealMap = this.dealSchemeVersionInfo(paramMap);
        String schemeVersionid = (String) outDealMap.get("schemeVersionid");// 草稿方案版本id

        // 校验任务
        Map<String, Object> taskIn = new HashMap<String, Object>();
        taskIn.put("id", taskId);
        taskIn.put("schemeVersionId", schemeVersionid);
        List<FollowTask> ftaskList = followTaskDao.selectByIdAndSchemeVerId(taskIn);
        if (CollectionUtils.isEmpty(ftaskList)) {
            throw (new AppException(ErrorCode.FOLLOWUP_EXCEPTION_TYPE_TASK_NOT_EXIST, "任务不存在，无法添加!"));
        }

        // 校验任务内容
        Map<String, Object> taskCntMap = new HashMap<String, Object>();
        taskCntMap.put("taskId", taskId);
        taskCntMap.put("schemeVersionid", schemeVersionid);
        taskCntMap.put("templId", templId);
        List<FollowTaskContent> ftcList = followTaskContDao.selectByTaskAndTempl(taskCntMap);
        if (!CollectionUtils.isEmpty(ftcList)) {
            throw (new AppException(ErrorCode.FOLLOWUP_EXCEPTION_TYPE_SCHEME_TASKCONT_TEMPL_ALREADY_EXIST,
                    "任务下已经存在该内容模板，无法重复添加!"));
        }

        // 校验内容模板是否存在
        Map<String, Object> cntTemplIn = new HashMap<String, Object>();
        cntTemplIn.put("templId", templId);
        cntTemplIn.put("templVersion", templVersion);
        List<ContentTemplVersion> cntTemplList = cntTemplDao.selectContentDataNoTextByTempl(cntTemplIn);
        if (CollectionUtils.isEmpty(cntTemplList)) {
            throw (new AppException(ErrorCode.FOLLOWUP_EXCEPTION_TYPE_QUES_TEMPLVERSION_NOT_EXIST, "内容模板不存在，无法添加!"));
        }

        // 任务下新增内容模板
        String taskCntId = SeqUtil.getSeqNo(Constants.SEQ_NO_FOR_TASK_CONTID);
        outMap.put("taskContId", taskCntId);

        FollowTaskContent ftcVo = new FollowTaskContent();
        ftcVo.setCreateTime(updateTime);
        ftcVo.setId(taskCntId);
        ftcVo.setSchemeVersionid(schemeVersionid);
        ftcVo.setSeqNo((Integer) taskInfoMap.get("seqNo"));
        ftcVo.setTaskId(taskId);
        ftcVo.setTemplId(templId);
        ftcVo.setTemplVersion(templVersion);
        ftcVo.setUpdateAccept(updateAccept);
        ftcVo.setUpdateTime(updateTime);
        followTaskContDao.saveTaskContInfo(ftcVo);

        // 入操作流水记录表 ia_operation_record
        Map<String, Object> paramRecord = new HashMap<String, Object>();
        paramRecord.put("userName", "");
        paramRecord.put("userId", "");
        paramRecord.put("queueId", "");
        paramRecord.put("authorId", authorId);
        paramRecord.put("opTime", updateTime);
        paramRecord.put("type", Constants.DOCTOR_ACTIVE_BUSI_TYPE_10);
        paramRecord.put("opUsertype", Constants.OPCODE_TYPE_DOCTOR);
        paramRecord.put("authorName", authorName);
        paramRecord.put("opCode", opCode);
        paramRecord.put("updateAccept", updateAccept);
        paramRecord.put("tenantId", tenantId);
        paramRecord.put("remark", oprInfoMap.get("opNote"));
        paramRecord.put("opType", oprInfoMap.get("opType"));
        paramRecord.put("taskId", taskId);
        Map<String, Object> outRecord = patientInfoHisService.buildOperationRecord(paramRecord);
        patientOperationRecordDao.saveOperationRecord(outRecord);

        return outMap;
    }

    // 删除当前方案当前任务下某项任务内容接口实现
    @Override
    @Transactional
    public Map<String, Object> removeSchemeTaskCont(Map<String, Object> paramMap) throws Exception {
        Map<String, Object> argMap = new HashMap<String, Object>(paramMap);
        Map<String, Object> outMap = new HashMap<String, Object>();

        Map<String, Object> oprInfoMap = ToolUtils.typeCast(argMap.get("oprInfo"));
        Map<String, Object> taskInfoMap = ToolUtils.typeCast(argMap.get("taskInfo"));

        String authorName = (String) oprInfoMap.get("authorName");
        String updateTime = (String) oprInfoMap.get("updateTime");
        String authorId = (String) oprInfoMap.get("authorId");
        String updateAccept = (String) oprInfoMap.get("updateAccept");
        String tenantId = (String) oprInfoMap.get("tenantId");
        String opCode = (String) oprInfoMap.get("opCode");

        String taskId = (String) taskInfoMap.get("taskId");
        String taskCntId = (String) taskInfoMap.get("taskContId");

        // 调用统一方法，将现有版本备份，新增版本
        Map<String, Object> outDealMap = this.dealSchemeVersionInfo(paramMap);
        String schemeVersionid = (String) outDealMap.get("schemeVersionid");// 草稿方案版本id

        // 删除任务内容
        Map<String, Object> taskCntMap = new HashMap<String, Object>();
        taskCntMap.put("id", taskCntId);
        taskCntMap.put("schemeVersionid", schemeVersionid);
        int remRet = followTaskContDao.removeTaskContInfo(taskCntMap);
        if (0 == remRet) {
            throw (new AppException(ErrorCode.FOLLOWUP_EXCEPTION_TYPE_SCHEME_TASKCONT_TEMPL_ALREADY_EXIST,
                    "任务下无此任务内容，删除失败!"));
        }

        // 入操作流水记录表 ia_operation_record
        Map<String, Object> paramRecord = new HashMap<String, Object>();
        paramRecord.put("userName", "");
        paramRecord.put("userId", "");
        paramRecord.put("queueId", "");
        paramRecord.put("authorId", authorId);
        paramRecord.put("opTime", updateTime);
        paramRecord.put("type", Constants.DOCTOR_ACTIVE_BUSI_TYPE_10);
        paramRecord.put("opUsertype", Constants.OPCODE_TYPE_DOCTOR);
        paramRecord.put("authorName", authorName);
        paramRecord.put("opCode", opCode);
        paramRecord.put("updateAccept", updateAccept);
        paramRecord.put("tenantId", tenantId);
        paramRecord.put("remark", oprInfoMap.get("opNote"));
        paramRecord.put("opType", oprInfoMap.get("opType"));
        paramRecord.put("taskId", taskId);
        Map<String, Object> outRecord = patientInfoHisService.buildOperationRecord(paramRecord);
        patientOperationRecordDao.saveOperationRecord(outRecord);

        return outMap;
    }

    // 模板问卷内容查询接口实现
    public Map<String, Object> listTemplCont(Map<String, Object> mapIn) throws Exception {
        Map<String, Object> outMap = new HashMap<String, Object>();
        List<Object> conDataList = new ArrayList<Object>();
        String templId = (String) mapIn.get("templId");
        Integer templVersion = (Integer) mapIn.get("templVersion");

        // 获取内容模板
        HashMap<String, Object> contVerMap = new HashMap<String, Object>();
        contVerMap.put("templId", templId);
        contVerMap.put("templVersion", templVersion);
        List<ContentTemplVersion> ctvList = cntTemplDao.selectContentDataByTempl(contVerMap);
        if (CollectionUtils.isEmpty(ctvList)) {
            throw new AppException(ErrorCode.FOLLOWUP_EXCEPTION_TYPE_QUES_TEMPL_NOT_EXIST, "未查询到标记模板版本记录！");
        }
        ContentTemplVersion ctv = ctvList.get(0);

        String templDataStr = ctv.getTemplData();
        if (StringUtils.isEmpty(templDataStr)) {
            throw new AppException(ErrorCode.FOLLOWUP_EXCEPTION_TYPE_QUES_TEMPLDATA_IS_NULL, "标记模板内容为空！");
        }

        // 数据库默认配置为json数组格式
        JSONArray templJsonArray = null;
        try {
            templJsonArray = JSON.parseArray(templDataStr);
            conDataList.add(templJsonArray);
        } catch (JSONException arex) {
            logger.error("任务内容模板格式配置错误，非json数组格式： " + arex.getMessage());

            // 非json数组格式，则按json格式再解析
            JSONObject templJsonObject = null;
            try {
                templJsonObject = JSON.parseObject(templDataStr);
                conDataList.add(templJsonObject);
            } catch (JSONException exobj) {
                exobj.printStackTrace();
                // 后续重写异常类
                throw (new AppException(ErrorCode.FOLLOWUP_EXCEPTION_TYPE_QUES_TEMPLDATA_CONFIG_IRREGULAR,
                        "问卷模板配置错误，非json格式！"));
            }
        } catch (AppException appex) {
            throw (appex);
        } catch (Exception ex) {
            ex.printStackTrace();
            throw new AppException(ErrorCode.FOLLOWUP_EXCEPTION_TYPE_QUES_TEMPLDATA_CONFIG_IRREGULAR,
                    "问卷模板格式解析错误：" + ex.getMessage());
        }
        outMap.put("questiones", conDataList);

        return outMap;
    }
}
